﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text;

using Fuse8.DomainFramework.Domain;
using Fuse8.DomainFramework.Common;

namespace Fuse8.DomainFramework.ValidationService
{
    /// <summary>
    /// Chain of responsibility
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseEntityValidationService<T> : IEntityValidationService<T> where T : class, IEntityObject
    {
        #region Properties

        /// <summary>
        /// 
        /// </summary>
        public IEntityValidationService<T> Successor 
        { 
            get; 
            protected set; 
        }

        #endregion

        #region IEntityValidationService<T> Members

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityObject"></param>
        /// <param name="actionType"></param>
        /// <returns></returns>
        public virtual ValidationResult Validate(T entityObject, ValidationActionType actionType)
        {
            Guard.ArgumentNotNull(entityObject, "entityObject");

            return Successor != null ?
                Successor.Validate(entityObject, actionType) :
                new ValidationResult { IsValid = true };
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="validator"></param>
        public void SetSuccessor(IEntityValidationService<T> validator)
        {
            Guard.ArgumentNotNull(validator, "validator");

            Successor = validator;
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        protected ValidationResult GlueResults(IEnumerable<ValidationResult> source)
        {
            Guard.ArgumentNotNull(source, "source");

            return source.Aggregate(
                (counter, next) =>
                {
                    counter.IsValid &= next.IsValid;

                    StringBuilder sb = new StringBuilder();

                    if (!string.IsNullOrEmpty(counter.ValidationMessage))
                    {
                        sb.AppendLine(counter.ValidationMessage);
                    }
                    sb.AppendLine(next.ValidationMessage);

                    counter.ValidationMessage = sb.ToString();

                    return counter;
                });
        }
    }
}
